{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "376b5e98-d9a9-4792-92f9-314920d5d8ad",
   "metadata": {},
   "source": [
    "# 面向对象编程\r\n",
    "\r\n",
    "面向对象编程（OOP）是一种程序设计范式，它使用“对象”作为基本构建块。在OOP中，对象是包含数据（属性）和可以操作这些数据的程序代码（方法）的实体。让我们详细探讨面向对象编程的基本概念，它与面向过程编程的区别，以及它的优势。\r\n",
    "\r\n",
    "### 什么是面向对象编程？\r\n",
    "\r\n",
    "面向对象编程（OOP）是一种编程模式，它使用“对象”来模拟现实世界的行为和事物。在OOP中，每个对象都可以表示为具有属性（特征）和方法（行为）的类的实例。类相当于对象的蓝图或模板。\r\n",
    "\r\n",
    "#### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2ba588a9-2deb-460d-912a-0d1158169f80",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Buddy says Woof!\n",
      "Whiskers says Meow!\n"
     ]
    }
   ],
   "source": [
    "class Animal:\n",
    "    def __init__(self, name):\n",
    "        self.name = name  # 属性\n",
    "\n",
    "    def speak(self):  # 方法\n",
    "        raise NotImplementedError(\"Subclass must implement abstract method\")\n",
    "\n",
    "class Dog(Animal):\n",
    "    def speak(self):\n",
    "        return f'{self.name} says Woof!'\n",
    "\n",
    "class Cat(Animal):\n",
    "    def speak(self):\n",
    "        return f'{self.name} says Meow!'\n",
    "\n",
    "# 创建对象\n",
    "dog = Dog(\"Buddy\")\n",
    "cat = Cat(\"Whiskers\")\n",
    "\n",
    "print(dog.speak())  # Buddy says Woof!\n",
    "print(cat.speak())  # Whiskers says Meow!\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "475cde82-c707-474a-8e85-8605a5f6a7de",
   "metadata": {},
   "source": [
    "### 面向对象编程与面向过程编程的区别\n",
    "\n",
    "面向对象编程（OOP）与面向过程编程（POP）的主要区别在于它们的关注点和设计方法：\n",
    "\n",
    "- **面向过程编程**关注于执行的步骤和过程。它通过将程序分解为一组函数来解决问题，重点在于操作数据。\n",
    "- **面向对象编程**则是关注于操作的对象和对象之间的交互。它通过封装数据和操作数据的函数到对象中来解决问题。\n",
    "\n",
    "### 面向对象编程的优势\n",
    "\n",
    "1. **模块化和封装**：通过将数据和操作该数据的方法绑定在一起，OOP使得代码更加模块化和易于理解。每个对象的实现细节被封装起来，只暴露必要的接口给外界使用。\n",
    "2. **代码复用**：继承使得可以创建新的类来继承现有类的特性，这有助于代码的重用和扩展。\n",
    "3. **灵活性和可维护性**：多态性允许同一接口用于不同的数据类型。这提高了程序的灵活性，并且当需要修改、扩展或修复错误时，使得代码更易于维护。\n",
    "4. **易于理解**：OOP促进了更接近现实世界的思考和编程方式，使得理解和设计复杂系统变得更容易。\n",
    "\n",
    "通过上述讨论，我们可以看到面向对象编程提供了一种强大且灵活的方式来组织和设计软件。在实际应用中，它能帮助开发者创建出更加清晰、可维护和扩展的代码。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "41e8af68-e3e1-4b14-8eb9-7c0427746010",
   "metadata": {},
   "source": [
    "## 面向对象基本术语\n",
    "\n",
    "### 类与对象\n",
    "\n",
    "- **类**：是一种用于创建和管理新对象的模板，定义了一组属性和方法。\n",
    "- **对象**：是根据类定义创建的实例。每个对象都拥有类中定义的属性和方法。\n",
    "\n",
    "#### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5244c860-5002-4131-9658-516c05284209",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我的名字是张三，年龄是30岁。\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "    # 类中定义了两个属性：name 和 age\n",
    "    def __init__(self, name, age):\n",
    "        self.name = name  # 实例属性\n",
    "        self.age = age\n",
    "\n",
    "    # 类中定义了一个方法：introduce\n",
    "    def introduce(self):\n",
    "        return f\"我的名字是{self.name}，年龄是{self.age}岁。\"\n",
    "\n",
    "# 创建Person类的一个对象\n",
    "person = Person(\"张三\", 30)\n",
    "print(person.introduce())  # 输出: 我的名字是张三，年龄是30岁。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f616da04-a417-4ed1-a87d-83f1c2daa5da",
   "metadata": {},
   "source": [
    "### 属性与方法\n",
    "\n",
    "- **属性**：是类中定义的变量，代表对象的状态或数据。\n",
    "- **方法**：是类中定义的函数，代表对象的行为。\n",
    "\n",
    "### 封装、继承、多态性、抽象\n",
    "\n",
    "#### 封装\n",
    "\n",
    "- 封装是OOP的一个核心概念，它指的是隐藏对象的内部状态和实现细节，仅对外公开接口。封装可以防止外部代码随意修改对象内部的状态，保证了数据的安全性和完整性。\n",
    "\n",
    "#### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "b0e47f1d-1535-4e36-963c-edbf5f01432a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "存款成功\n",
      "账户余额：1500\n"
     ]
    }
   ],
   "source": [
    "class Account:\n",
    "    def __init__(self, owner, amount=0):\n",
    "        self.owner = owner\n",
    "        self.__amount = amount  # 私有属性\n",
    "\n",
    "    def deposit(self, amount):\n",
    "        if amount > 0:\n",
    "            self.__amount += amount\n",
    "            return \"存款成功\"\n",
    "        else:\n",
    "            return \"存款金额必须大于0\"\n",
    "\n",
    "    def show_balance(self):\n",
    "        return f\"账户余额：{self.__amount}\"\n",
    "\n",
    "account = Account(\"李四\", 1000)\n",
    "print(account.deposit(500))  # 输出: 存款成功\n",
    "print(account.show_balance())  # 输出: 账户余额：1500\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13eea67a-781a-46b1-aad3-01811cb04116",
   "metadata": {},
   "source": [
    "#### 继承\n",
    "\n",
    "- 继承允许我们定义一个类（子类）继承另一个类（父类）的属性和方法。通过继承，子类可以扩展或修改父类的行为。\n",
    "\n",
    "#### 多态性\n",
    "\n",
    "- 多态性是指不同类的对象对同一消息会作出不同的响应。即，不同的对象可以通过相同的接口执行不同的操作。\n",
    "\n",
    "#### 抽象\n",
    "\n",
    "- 抽象是简化复杂现实的过程，通过定义类的关键行为而忽略具体实现的方式。在Python中，可以通过抽象基类来实现抽象，强制子类实现特定的方法。\n",
    "\n",
    "### Python类的基本结构\n",
    "\n",
    "- **定义类**：使用`class`关键字来定义。\n",
    "- **创建对象**：通过调用类的构造方法（`__init__`）来创建对象。\n",
    "- **初始化属性**：`__init__`方法用于在创建对象时初始化属性。\n",
    "\n",
    "### 类的属性和方法\n",
    "\n",
    "- **实例属性**：属于类的各个实例的数据。\n",
    "- **类属性**：属于类本身的属性，由所有实例共享。\n",
    "- **实例方法**：需要通过对象来调用的方法，可以访问实例属性和类属性。\n",
    "- **类方法**：使用`@classmethod`装饰器定义，第一个参数是类对象（通常命名为`cls`），可以访问类属性但无法访问实例属性。\n",
    "- **静态方法**：使用`@staticmethod`装饰器定义，既不需要类对象也不需要实例对象作为第一个参数。\n",
    "\n",
    "#### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7b953ef8-88f0-45d7-a14d-2db22168d78b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我叫王五，我就读于高级中学。\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "class Student:\n",
    "    school_name = \"中学\"  # 类属性\n",
    "\n",
    "    def __init__(self, name):\n",
    "        self.name = name  # 实例属性\n",
    "\n",
    "    def introduce(self):  # 实例方法\n",
    "        return f\"我叫{self.name}，我就读于{self.school_name}。\"\n",
    "\n",
    "    @classmethod\n",
    "    def change_school_name(cls, new_name):  # 类方法\n",
    "        cls.school_name = new_name\n",
    "\n",
    "    @staticmethod\n",
    "    def is_school_day(day):  # 静态方法\n",
    "        if day in ['Saturday', 'Sunday']:\n",
    "            return False\n",
    "        return True\n",
    "\n",
    "# 使用类方法修改类属性\n",
    "Student.change_school_name(\"高级中学\")\n",
    "student = Student(\"王五\")\n",
    "print(student.introduce())  # 输出: 我叫王五，我就读于高级中学。\n",
    "\n",
    "# 调用静态方法\n",
    "print(Student.is_school_day('Monday'))  # 输出: True\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6995f212-51b6-4cf3-8c34-bf6fe3ff3837",
   "metadata": {},
   "source": [
    "### Python类的基本结构\n",
    "\n",
    "在Python中，类的基本结构包括类的定义、创建对象以及初始化属性。下面通过详细的代码示例和中文注释来逐一讲解这些概念。\n",
    "\n",
    "#### 定义类\n",
    "\n",
    "类是对象的蓝图和模板，通过关键字`class` 来定义。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f5de6b3c-8aef-4ffa-a999-d9b3b5e94977",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义一个名为Person的类\n",
    "class Person:\n",
    "    pass  # 使用pass语句表示一个空的代码块\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88724364-7275-4584-8a09-1ef5e9278947",
   "metadata": {},
   "source": [
    "#### 创建对象(实例化)\n",
    "\n",
    "对象是类的实例。当类被定义后，我们可以通过调用类（就像函数一样）来创建该类的实例。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "74e41da1-426d-409b-a578-57f2f49d8f61",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<__main__.Person object at 0x0000018298EC22C0>\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "    pass\n",
    "\n",
    "# 创建Person类的一个实例，并将其赋值给变量person\n",
    "person = Person()\n",
    "print(person)  # 输出类的实例，例如：<__main__.Person object at 0x000001>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23fa4784-a8f2-491f-889c-f8d4b67ee165",
   "metadata": {},
   "source": [
    "#### 初始化属性（`__init__` 方法）\n",
    "\n",
    "`__init__` 方法是一个特殊的方法，被称为类的构造器。当一个类的实例被创建时，`__init__` 方法自动调用，用于初始化对象。前后都是两个下划线。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "335022d5-3243-4273-a90f-1641a92b6f8c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "名字: 张三, 年龄: 28\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "    # __init__方法用于初始化对象的属性\n",
    "    def __init__(self, name, age):\n",
    "        self.name = name  # 实例属性name\n",
    "        self.age = age    # 实例属性age\n",
    "\n",
    "# 创建Person类的实例，需要传递name和age参数给__init__方法\n",
    "person = Person(\"张三\", 28)\n",
    "\n",
    "# 访问对象的属性\n",
    "print(f\"名字: {person.name}, 年龄: {person.age}\")\n",
    "# 输出: 名字: 张三, 年龄: 28\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddc01ea0-09e3-4573-9e37-3955924ebd0e",
   "metadata": {},
   "source": [
    "在上述示例中，Person 类通过__init__ 方法定义了两个属性：name 和 age。当我们创建一个Person 类的实例时，必须提供name 和 age 参数，这些参数被用来初始化对应的实例属性。\n",
    "\n",
    "通过这样的方式，__init__ 方法为对象的创建和初始化提供了极大的灵活性和控制力。它允许我们确保对象在使用前已经被正确地初始化，从而使得对象一旦被创建，就处于一个有效的状态。示例代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "005d4794-36ab-4b48-b6e6-ba7c68bd22eb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "名字: 张三, 年龄: 28\n"
     ]
    }
   ],
   "source": [
    "class Person:\n",
    "    pass  # 没有定义构造器\n",
    "\n",
    "# 即使没有显式定义__init__，也能创建Person类的实例\n",
    "person = Person()\n",
    "\n",
    "# 我们可以动态地添加属性\n",
    "person.name = \"张三\"\n",
    "person.age = 28\n",
    "\n",
    "print(f\"名字: {person.name}, 年龄: {person.age}\")\n",
    "# 输出: 名字: 张三, 年龄: 28\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93c78b78-eb2c-49e4-86c8-76fc76919b32",
   "metadata": {},
   "source": [
    "在这个示例中，`Person` 类没有定义`__init__`方法，所以它使用Python的默认构造器来创建实例。创建实例后，我们可以给这个实例动态添加属性。这种动态添加属性的方式提供了灵活性，但它也让代码变得不那么明确和易于理解，特别是在与其他开发者合作的大型项目中。因此，如果你的对象需要初始化一些属性，最好显式地定义一个`__init__`方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3582a5b8-e1b4-4188-a093-bbd5f76cdd36",
   "metadata": {},
   "source": [
    "### 类的属性和方法\n",
    "\n",
    "在Python中，类可以拥有两种属性：实例属性和类属性。同样，类中的方法可以分为三种：实例方法、类方法和静态方法。下面通过具体的例子详细解释这些概念。\n",
    "\n",
    "#### 实例属性与类属性\n",
    "\n",
    "- **实例属性**：属于类的单个实例，每个对象实例都拥有独立的实例属性副本。\n",
    "- **类属性**：属于类本身，被类的所有实例共享。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "4ed90138-d643-49f1-8160-39131e9458e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Alice 是一名 Engineer\n",
      "Bob 是一名 Manager\n",
      "Alice 工作在 Google\n"
     ]
    }
   ],
   "source": [
    "class Employee:\n",
    "    # 类属性\n",
    "    company = \"Google\"\n",
    "\n",
    "    # 构造函数中定义的是实例属性\n",
    "    def __init__(self, name, position):\n",
    "        self.name = name  # 实例属性\n",
    "        self.position = position  # 实例属性\n",
    "\n",
    "# 创建Employee类的两个实例\n",
    "emp1 = Employee(\"Alice\", \"Engineer\")\n",
    "emp2 = Employee(\"Bob\", \"Manager\")\n",
    "\n",
    "# 访问实例属性\n",
    "print(f\"{emp1.name} 是一名 {emp1.position}\")\n",
    "print(f\"{emp2.name} 是一名 {emp2.position}\")\n",
    "\n",
    "# 访问类属性\n",
    "print(f\"{emp1.name} 工作在 {Employee.company}\")\n",
    "# 输出: Alice 是一名 Engineer\n",
    "#      Bob 是一名 Manager\n",
    "#      Alice 工作在 Google\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "441a459f-8196-4b5b-ba75-646e4f52f798",
   "metadata": {},
   "source": [
    "#### 实例方法、类方法（@classmethod）、静态方法（@staticmethod）\n",
    "\n",
    "- **实例方法**：第一个参数是`self`，代表类的实例。它可以访问和修改对象的属性。\n",
    "- **类方法**：使用装饰器`@classmethod`标记，其第一个参数是`cls`，代表类本身。它可以访问和修改类属性。\n",
    "- **静态方法**：使用装饰器`@staticmethod`标记，不自动传递实例或类的引用。它主要用于放置在逻辑上属于类的方法，但不需要类或实例中的任何信息。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "44db386a-3ff4-478f-b839-fd63764b30d3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "圆的面积是: 78.5\n",
      "更新π值后，圆的面积是: 78.53975\n",
      "半径为-5的圆是否有效？ False\n"
     ]
    }
   ],
   "source": [
    "class Circle:\n",
    "    pi = 3.14  # 类属性\n",
    "\n",
    "    def __init__(self, radius):\n",
    "        self.radius = radius  # 实例属性\n",
    "\n",
    "    # 实例方法\n",
    "    def area(self):\n",
    "        return self.pi * (self.radius ** 2)\n",
    "\n",
    "    # 类方法\n",
    "    @classmethod\n",
    "    def set_pi(cls, value):\n",
    "        cls.pi = value\n",
    "\n",
    "    # 静态方法\n",
    "    @staticmethod\n",
    "    def is_valid_radius(radius):\n",
    "        return radius > 0\n",
    "\n",
    "circle = Circle(5)\n",
    "print(f\"圆的面积是: {circle.area()}\")  # 使用实例方法计算面积\n",
    "# 输出: 圆的面积是: 78.5\n",
    "\n",
    "Circle.set_pi(3.14159)  # 使用类方法修改类属性pi的值\n",
    "print(f\"更新π值后，圆的面积是: {circle.area()}\")\n",
    "# 输出: 更新π值后，圆的面积是: 78.53975\n",
    "\n",
    "print(f\"半径为-5的圆是否有效？ {Circle.is_valid_radius(-5)}\")\n",
    "# 使用静态方法检查半径值是否有效\n",
    "# 输出: 半径为-5的圆是否有效？ False\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e20bb60-ca5b-47d1-b958-950d9d03ae74",
   "metadata": {},
   "source": [
    "静态方法可以不实例化类而直接使用。静态方法通过装饰器`@staticmethod`定义，它不接受类（`cls`）或实例（`self`）作为首个参数。这意味着静态方法既可以通过类名直接调用，也可以通过类的实例调用，但它不依赖于类的实例本身。这使得静态方法成为实现与类逻辑相关但不需要类或实例状态的功能的理想选择。\n",
    "\n",
    "### 示例代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f2765744-977d-46ae-8691-d842fb8cf102",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 + 7 = 12\n",
      "3 * 4 = 12\n",
      "10 + 2 = 12\n"
     ]
    }
   ],
   "source": [
    "class MathOperations:\n",
    "    @staticmethod\n",
    "    def add(x, y):\n",
    "        return x + y\n",
    "\n",
    "    @staticmethod\n",
    "    def multiply(x, y):\n",
    "        return x * y\n",
    "\n",
    "# 直接通过类调用静态方法\n",
    "result_add = MathOperations.add(5, 7)\n",
    "print(f\"5 + 7 = {result_add}\")\n",
    "# 输出: 5 + 7 = 12\n",
    "\n",
    "# 直接通过类调用静态方法\n",
    "result_multiply = MathOperations.multiply(3, 4)\n",
    "print(f\"3 * 4 = {result_multiply}\")\n",
    "# 输出: 3 * 4 = 12\n",
    "\n",
    "# 也可以通过类的实例调用静态方法，但这并不常见\n",
    "math_instance = MathOperations()\n",
    "result_add_instance = math_instance.add(10, 2)\n",
    "print(f\"10 + 2 = {result_add_instance}\")\n",
    "# 输出: 10 + 2 = 12\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e38ee46b-436c-4110-848f-495ca6ddce67",
   "metadata": {},
   "source": [
    "在这个例子中，`MathOperations`类包含了两个静态方法：`add` 和 `multiply`。这些方法可以不创建类的实例而直接被调用。这表明静态方法适用于那些不需要访问类的属性或实例属性的功能。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9896ecd4-ff74-4227-8481-9b1cafc3427d",
   "metadata": {},
   "source": [
    "### 封装\n",
    "\n",
    "封装是面向对象编辑（OOP）中的一个核心概念，它涉及到在类中隐藏特定的属性和方法，仅对外提供有限的接口进行交互。这样做有助于限制外部对对象内部状态的直接访问，从而增加了代码的安全性和灵活性。接下来，我们将通过一系列详细的例子来展示如何在Python中实现封装，包括使用私有属性、方法，以及通过getter和setter方法以及`@property`装饰器来访问和修改这些属性。\n",
    "\n",
    "### 为何需要封装\n",
    "\n",
    "封装主要有以下几个好处：\n",
    "\n",
    "1. **安全性**：隐藏对象的内部状态，防止外部直接访问，减少因错误操作导致的问题。\n",
    "2. **易用性**：提供简单的接口操作复杂的逻辑，增加代码的易用性。\n",
    "3. **可维护性**：内部实现的改变不会影响到使用该对象的代码，提高代码的可维护性。\n",
    "\n",
    "### 如何实现封装\n",
    "\n",
    "在Python中，封装可以通过使用前缀为单个或双下划线（`_`或`__`）的命名来实现属性和方法的访问限制。\n",
    "\n",
    "#### 私有属性与方法\n",
    "\n",
    "私有属性和方法是类中对外隐藏的部分，只能在类的内部访问。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7dfa2202-e225-478f-8de0-5e8b67297821",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "账户持有人: 张三\n",
      "账户余额: 10000\n"
     ]
    }
   ],
   "source": [
    "class Account:\n",
    "    def __init__(self, owner, amount):\n",
    "        self.owner = owner  # 公开属性\n",
    "        self.__balance = amount  # 私有属性\n",
    "\n",
    "    def __display_balance(self):  # 私有方法\n",
    "        return f\"账户余额: {self.__balance}\"\n",
    "\n",
    "    def show_info(self):\n",
    "        print(f\"账户持有人: {self.owner}\")\n",
    "        print(self.__display_balance())  # 在类内部调用私有方法\n",
    "\n",
    "account = Account(\"张三\", 10000)\n",
    "account.show_info()\n",
    "# 输出: 账户持有人: 张三\n",
    "#       账户余额: 10000\n",
    "\n",
    "# 尝试直接访问私有属性和方法会导致错误\n",
    "# print(account.__balance)  # 错误\n",
    "# account.__display_balance()  # 错误\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d57c6485-dd0d-4e92-b34c-43afe979f70f",
   "metadata": {},
   "source": [
    "#### 使用getter和setter方法操作属性\n",
    "\n",
    "为了安全地访问和修改私有属性，我们可以定义公开的getter和setter方法。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b68e1abf-7864-4a21-a0ad-5bd841baa5fd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20000\n",
      "15000\n"
     ]
    }
   ],
   "source": [
    "class Account:\n",
    "    def __init__(self, owner, amount):\n",
    "        self.owner = owner\n",
    "        self.__balance = amount\n",
    "\n",
    "    # Getter方法\n",
    "    def get_balance(self):\n",
    "        return self.__balance\n",
    "\n",
    "    # Setter方法\n",
    "    def set_balance(self, amount):\n",
    "        if amount >= 0:\n",
    "            self.__balance = amount\n",
    "        else:\n",
    "            print(\"余额不能为负数\")\n",
    "\n",
    "account = Account(\"李四\", 20000)\n",
    "print(account.get_balance())  # 通过getter方法访问私有属性\n",
    "account.set_balance(15000)  # 通过setter方法修改私有属性\n",
    "print(account.get_balance())\n",
    "# 输出: 20000\n",
    "#       15000\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aafd93bb-e7fc-49af-9f03-dc6d8c38dcd1",
   "metadata": {},
   "source": [
    "#### 使用装饰器（`@property`）\n",
    "\n",
    "Python提供了一个内置的`@property`装饰器，使得我们可以用更简洁的方式定义getter和setter方法。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "dd6f5de0-c790-40bc-8ffd-e971ca4c71f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "30000\n",
      "25000\n"
     ]
    }
   ],
   "source": [
    "class Account:\n",
    "    def __init__(self, owner, amount):\n",
    "        self.owner = owner\n",
    "        self.__balance = amount\n",
    "\n",
    "    @property\n",
    "    def balance(self):\n",
    "        return self.__balance\n",
    "\n",
    "    @balance.setter\n",
    "    def balance(self, amount):\n",
    "        if amount >= 0:\n",
    "            self.__balance = amount\n",
    "        else:\n",
    "            print(\"余额不能为负数\")\n",
    "\n",
    "account = Account(\"王五\", 30000)\n",
    "print(account.balance)  # 直接访问属性\n",
    "account.balance = 25000  # 直接设置属性\n",
    "print(account.balance)\n",
    "# 输出: 30000\n",
    "#       25000\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be3f8317-5c59-4dc2-b4d1-a02172495bd5",
   "metadata": {},
   "source": [
    "`@property` 是 Python 中用于创建 property 的内置装饰器。它允许您定义一个方法，并将其用作属性来访问，而不是通过直接访问方法。这种技术在面向对象编程中常用于实现 getter 和 setter 方法，以确保对属性的访问和修改都通过特定的方法进行，从而增加了代码的灵活性和可维护性。\n",
    "\n",
    "下面是 `@property` 装饰器的基本用法："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d609f7b-335c-4f30-abaa-28b430295e17",
   "metadata": {},
   "source": [
    "这个示例演示了如何使用 `@property` 装饰器创建一个具有 getter 和 setter 方法的属性。\n",
    "\n",
    "1. `Account` 类具有两个参数 `owner` 和 `amount`，分别表示账户的所有者和初始金额。\n",
    "2. `self.owner = owner` 将传入的所有者参数赋值给实例的 `owner` 属性。\n",
    "3. `self.__balance = amount` 将传入的金额参数赋值给类的私有属性 `__balance`。请注意，`__balance` 被双下划线包围，这意味着它是一个私有属性，外部不应该直接访问它。\n",
    "4. `@property` 装饰器将 `balance` 方法转换为一个属性，因此可以像访问属性一样访问 `balance` 方法。\n",
    "5. `balance` 方法只有一个 getter 方法，用于返回私有属性 `__balance` 的值。\n",
    "6. `@balance.setter` 装饰器创建了一个 setter 方法，允许修改私有属性 `__balance` 的值。在这个 setter 方法中，如果传入的金额大于等于 0，则将其赋值给 `__balance`；否则，打印一条错误消息，表示余额不能为负数。\n",
    "\n",
    "在代码的后续部分，我们创建了一个名为 `account` 的 `Account` 类的实例，初始化所有者为 `\"王五\"`，初始金额为 `30000`。 然后我们直接访问了 `balance` 属性，并打印出当前余额。 接着，我们通过直接设置 `balance` 属性，将余额修改为 `25000`，然后再次打印出当前余额。\n",
    "\n",
    "最后的输出显示了余额的变化。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77110e1f-79e9-4e43-9cd2-41348b76c8e9",
   "metadata": {},
   "source": [
    "### 继承\n",
    "\n",
    "继承是面向对象编程中的一个核心概念，它允许我们定义一个类以继承另一个类的属性和方法，从而实现代码的复用。在Python中，继承的实现非常直接和灵活，包括基类（或父类）与派生类（或子类）、方法的重写，以及多重继承的支持。下面通过一系列的例子来展示这些概念。\n",
    "\n",
    "### 如何继承一个类\n",
    "\n",
    "在Python中，继承可以通过在类定义时，在类名后面的括号中指定基类来实现。\n",
    "\n",
    "#### 基类与派生类\n",
    "\n",
    "基类（或父类）是被继承的类，派生类（或子类）是继承基类的类。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "01f4aecc-50dd-4ae4-8bde-3856c3a96c68",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "奥迪A4的速度是: 180km/h\n"
     ]
    }
   ],
   "source": [
    "# 定义一个基类\n",
    "class Vehicle:\n",
    "    def __init__(self, name, speed):\n",
    "        self.name = name\n",
    "        self.speed = speed\n",
    "\n",
    "    def get_speed(self):\n",
    "        return f\"{self.name}的速度是: {self.speed}km/h\"\n",
    "\n",
    "# 定义一个派生类，继承自Vehicle\n",
    "class Car(Vehicle):\n",
    "    pass\n",
    "\n",
    "# 创建Car的实例\n",
    "car = Car(\"奥迪A4\", 180)\n",
    "print(car.get_speed())\n",
    "# 输出: 奥迪A4的速度是: 180km/h\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65a2681d-156f-4457-a0a3-4b6b4211d54c",
   "metadata": {},
   "source": [
    "### 重写方法\n",
    "\n",
    "派生类可以重写继承自基类的方法，以实现不同的功能。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "bcdba683-c846-4f54-8b70-7fc53ed2bfb7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "电动车静音启动\n"
     ]
    }
   ],
   "source": [
    "class Vehicle:\n",
    "    def start(self):\n",
    "        return \"车辆启动\"\n",
    "\n",
    "class ElectricVehicle(Vehicle):\n",
    "    # 重写start方法\n",
    "    def start(self):\n",
    "        return \"电动车静音启动\"\n",
    "\n",
    "ev = ElectricVehicle()\n",
    "print(ev.start())\n",
    "# 输出: 电动车静音启动\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c45fbbf-a45d-4e18-b59f-b414ca30cb09",
   "metadata": {},
   "source": [
    "### 多重继承\n",
    "\n",
    "Python支持多重继承，即一个类可以继承多个基类。\n",
    "\n",
    "##### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "eb57c86f-a836-4f7b-ba50-9db9d64639c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在充电...\n",
      "正在驾驶...\n"
     ]
    }
   ],
   "source": [
    "class Electric:\n",
    "    def charge(self):\n",
    "        return \"正在充电...\"\n",
    "\n",
    "class Car:\n",
    "    def drive(self):\n",
    "        return \"正在驾驶...\"\n",
    "\n",
    "# 多重继承，ElectricCar同时继承自Electric和Car\n",
    "class ElectricCar(Electric, Car):\n",
    "    pass\n",
    "\n",
    "ecar = ElectricCar()\n",
    "print(ecar.charge())  # 来自Electric\n",
    "print(ecar.drive())   # 来自Car\n",
    "# 输出: 正在充电...\n",
    "#       正在驾驶...\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a63a9fed-d779-484d-8dc5-e8d81a99ca2e",
   "metadata": {},
   "source": [
    "在多重继承中，如果存在方法重名，Python会根据类的声明顺序从左到右搜索基类，直到找到为止。这个规则是多重继承中解决方法解析顺序（Method Resolution Order, MRO）的关键。\n",
    "\n",
    "通过继承，我们可以创建结构化的代码，避免重复，并提高代码的可读性和可维护性。在设计类的层次结构时，合理利用继承关系能够让我们的程序更加灵活和强大。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea806308-93d3-496a-87c4-30f342309c90",
   "metadata": {},
   "source": [
    "### 多态性\n",
    "\n",
    "多态性是面向对象编程中的一个核心概念，它指的是能够使用相同的接口来操作不同的基本数据类型或对象。多态性提供了一种机制，让方法可以做到在不同情况下有不同的实现方式。这种能力不仅增加了程序的灵活性，也使得代码更加易于扩展和维护。\n",
    "\n",
    "#### 什么是多态性\n",
    "\n",
    "多态性允许我们将不同的对象视为它们共同的父类类型来处理，而实际上它们可以是任何派生自该父类的子类。这意味着不同子类的对象可以根据同一个方法调用，执行各自实现的方法。\n",
    "\n",
    "### 如何在Python中实现多态性\n",
    "\n",
    "在Python中，多态是隐式实现的。Python是一种动态类型语言，不需要像Java或C++那样显式声明类型，这让多态性的实现变得自然而然。Python中的多态表现为不同类的对象能够响应相同的消息（方法调用）。\n",
    "\n",
    "#### 示例1：基于共同的父类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "57b174f1-8a05-49d5-be8a-93efb23dc095",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "汪汪！\n",
      "喵喵！\n"
     ]
    }
   ],
   "source": [
    "class Animal:\n",
    "    def speak(self):\n",
    "        pass\n",
    "\n",
    "class Dog(Animal):\n",
    "    def speak(self):\n",
    "        return \"汪汪！\"\n",
    "\n",
    "class Cat(Animal):\n",
    "    def speak(self):\n",
    "        return \"喵喵！\"\n",
    "\n",
    "def make_animal_speak(animal):\n",
    "    print(animal.speak())\n",
    "\n",
    "dog = Dog()\n",
    "cat = Cat()\n",
    "\n",
    "make_animal_speak(dog)  # 输出: 汪汪！\n",
    "make_animal_speak(cat)  # 输出: 喵喵！\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35eba56f-a1b6-4c54-bf3c-3d8ee9aa122c",
   "metadata": {},
   "source": [
    "在这个例子中，`Dog`和`Cat`类都继承自`Animal`类，并重写了`speak`方法。函数`make_animal_speak`接受任何`Animal`的实例，并调用它的`speak`方法，展现了多态性。\n",
    "\n",
    "#### 示例2：不基于共同的父类（鸭子类型）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "3488e815-4304-4dcd-b62e-87afdd29fa8f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "汪汪！\n",
      "我是机器人！\n"
     ]
    }
   ],
   "source": [
    "class Dog:\n",
    "    def speak(self):\n",
    "        return \"汪汪！\"\n",
    "\n",
    "class Robot:\n",
    "    def speak(self):\n",
    "        return \"我是机器人！\"\n",
    "\n",
    "def make_it_speak(entity):\n",
    "    print(entity.speak())\n",
    "\n",
    "dog = Dog()\n",
    "robot = Robot()\n",
    "\n",
    "make_it_speak(dog)  # 输出: 汪汪！\n",
    "make_it_speak(robot)  # 输出: 我是机器人！\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "479c7930-0f6e-4c9e-bebf-1711ac34dfd3",
   "metadata": {},
   "source": [
    "即使`Dog`和`Robot`没有共同的父类，只要它们实现了相同的方法，它们就可以通过相同的接口调用，展现了Python的\"鸭子类型\"。\n",
    "\n",
    "### 动态绑定\n",
    "\n",
    "动态绑定是指在程序运行时（而非编译时），对象与方法或属性绑定的机制。在Python中，这意味着我们可以在运行时给对象添加属性或方法，或者改变已有方法的实现。\n",
    "\n",
    "#### 示例代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "2b072c62-7bdf-4ae7-af05-223d4dd67444",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "鸟儿飞翔\n",
      "鸟儿游泳\n",
      "鸟儿在天空翱翔\n"
     ]
    }
   ],
   "source": [
    "class Bird:\n",
    "    def fly(self):\n",
    "        return \"鸟儿飞翔\"\n",
    "\n",
    "# 实例化Bird类\n",
    "bird = Bird()\n",
    "print(bird.fly())  # 输出: 鸟儿飞翔\n",
    "\n",
    "# 动态绑定方法\n",
    "def swim(self):\n",
    "    return \"鸟儿游泳\"\n",
    "\n",
    "# 将swim方法绑定到bird实例\n",
    "Bird.swim = swim\n",
    "print(bird.swim())  # 输出: 鸟儿游泳\n",
    "\n",
    "# 甚至可以修改已有方法\n",
    "Bird.fly = lambda self: \"鸟儿在天空翱翔\"\n",
    "print(bird.fly())  # 输出: 鸟儿在天空翱翔\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52d551d5-74cd-4eb0-bd53-0f68464d5e70",
   "metadata": {},
   "source": [
    "###  抽象\n",
    "\n",
    "在面向对象编程中，抽象是一种只展示操作方式而隐藏具体实现的方法。它能够帮助我们将类的接口与实现分离，这样就可以在不影响外部调用的情况下改变具体实现。这种方式可以增加代码的可用性和可维护性。\n",
    "\n",
    "#### 抽象类与抽象方法\n",
    "\n",
    "- **抽象类**：是一种不能被实例化的类，它声明了一组方法，但不一定提供所有方法的实现。抽象类通常作为基类，要求子类实现特定的抽象方法。\n",
    "- **抽象方法**：在抽象类内部定义，是一种没有具体实现的方法。它用来声明子类必须提供的功能接口。抽象方法在父类中通常没有定义具体的内容，留给子类根据具体情况实现。\n",
    "\n",
    "#### abc模块的应用\n",
    "\n",
    "Python通过`abc`（Abstract Base Classes）模块提供了对抽象类的支持。使用`abc`模块可以创建抽象基础类，以及在这些类中定义抽象方法。\n",
    "\n",
    "##### 抽象类的作用\n",
    "\n",
    "1. 定义了子类应遵循的接口规范。\n",
    "2. 可以包含抽象方法和具体方法。\n",
    "3. 抽象类不能被实例化，尝试实例化会抛出TypeError。\n",
    "\n",
    "##### 抽象方法要不要实现\n",
    "\n",
    "抽象方法在抽象类中不需要实现，其实现留给继承抽象类的子类。如果子类没有实现所有的抽象方法，那么这个子类也不能被实例化。\n",
    "\n",
    "#### 示例代码：使用`abc`模块定义抽象类和抽象方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f080cb27-b4ae-4743-8b87-b85ef92c617d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "汽车在行驶\n",
      "自行车在行驶\n"
     ]
    }
   ],
   "source": [
    "from abc import ABC, abstractmethod\n",
    "\n",
    "# 定义一个抽象类\n",
    "class Vehicle(ABC):\n",
    "    @abstractmethod\n",
    "    def go(self):\n",
    "        pass\n",
    "\n",
    "class Car(Vehicle):\n",
    "    def go(self):\n",
    "        return \"汽车在行驶\"\n",
    "\n",
    "class Bicycle(Vehicle):\n",
    "    def go(self):\n",
    "        return \"自行车在行驶\"\n",
    "\n",
    "# 尝试实例化抽象类会抛出错误\n",
    "# vehicle = Vehicle()  # TypeError: Can't instantiate abstract class Vehicle with abstract methods go\n",
    "\n",
    "# 子类实例化并调用实现的抽象方法\n",
    "car = Car()\n",
    "print(car.go())  # 输出: 汽车在行驶\n",
    "bicycle = Bicycle()\n",
    "print(bicycle.go())  # 输出: 自行车在行驶\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1048f3bd-9ce7-405b-9704-8015787f8645",
   "metadata": {},
   "source": [
    "在这个例子中，`Vehicle`类是一个抽象类，它定义了一个抽象方法`go`。`Car`和`Bicycle`类继承自`Vehicle`并实现了`go`方法。这展示了如何在Python中通过`abc`模块定义和使用抽象类和抽象方法。\r\n",
    "\r\n",
    "抽象类和抽象方法是面向对象设计中非常重要的概念，它们提供了一个框架，要求派生类遵循特定的接口规范，这在设计大型系统和库时尤其有用。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "401485e3-2595-480a-96de-a34614331ab2",
   "metadata": {},
   "source": [
    "#### 组合与聚合\n",
    "\n",
    "组合和聚合都是用来表示类之间的关系，它们都是通过在一个类中包含另一个类的实例来实现的。与继承相比，组合和聚合提供了更大的灵活性，它们使得我们能够更容易地修改或扩展功能。\n",
    "\n",
    "- **组合**：表示一种强关系，例如汽车和发动机的关系。如果汽车不存在了，发动机也就没有存在的意义了。\n",
    "- **聚合**：表示一种弱关系，例如图书馆和书的关系。图书馆不存在了，书还是可以存在的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "d9a6c2a4-c8cd-4bd5-be98-17313a2c1d4b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "引擎启动\n"
     ]
    }
   ],
   "source": [
    "# 组合示例\n",
    "class Engine:\n",
    "    def start(self):\n",
    "        print(\"引擎启动\")\n",
    "\n",
    "class Car:\n",
    "    def __init__(self):\n",
    "        self.engine = Engine()\n",
    "\n",
    "    def start(self):\n",
    "        self.engine.start()  # 调用引擎的启动方法\n",
    "\n",
    "car = Car()\n",
    "car.start()  # 输出: 引擎启动\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4093df8-4b42-498b-9cb6-5e0bdeac3e71",
   "metadata": {},
   "source": [
    "聚合描述了一种“拥有”关系，其中一个类作为容器包含另一个类的对象，但两者生命周期并不一致。这意味着当容器对象被销毁时，其成员对象可以继续存在。下面是一个聚合的例子，用图书馆和书的关系来说明。\n",
    "\n",
    "在这个例子中，Library类包含多个Book实例。图书馆可以拥有多本书，但书可以在没有图书馆的情况下独立存在（例如，可以借出或属于多个图书馆）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "ec0f4155-65bc-46d4-838a-7c849eadc857",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "'Python编程' by 张三\n",
      "'深入学习Java' by 李四\n",
      "'Python编程' by 张三\n"
     ]
    }
   ],
   "source": [
    "class Book:\n",
    "    def __init__(self, title, author):\n",
    "        self.title = title\n",
    "        self.author = author\n",
    "\n",
    "    def __str__(self):\n",
    "        return f\"'{self.title}' by {self.author}\"\n",
    "\n",
    "class Library:\n",
    "    def __init__(self):\n",
    "        self.books = []\n",
    "\n",
    "    def add_book(self, book):\n",
    "        self.books.append(book)\n",
    "\n",
    "    def display_books(self):\n",
    "        for book in self.books:\n",
    "            print(book)\n",
    "\n",
    "# 创建几本书\n",
    "book1 = Book(\"Python编程\", \"张三\")\n",
    "book2 = Book(\"深入学习Java\", \"李四\")\n",
    "\n",
    "# 创建图书馆实例并添加书籍\n",
    "library = Library()\n",
    "library.add_book(book1)\n",
    "library.add_book(book2)\n",
    "\n",
    "# 显示图书馆中的书籍\n",
    "library.display_books()\n",
    "# 输出:\n",
    "# 'Python编程' by 张三\n",
    "# '深入学习Java' by 李四\n",
    "\n",
    "# 即使图书馆对象被删除，书籍对象仍然存在\n",
    "del library\n",
    "print(book1)  # 'Python编程' by 张三\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3cb03f9f-bee0-44b1-811a-b0d30b183a04",
   "metadata": {},
   "source": [
    "让我们设计一个简单的在线购物系统，展示面向对象编程的核心概念，包括类和对象、继承、聚合与组合、以及多态性。我们的系统将包含用户、商品、订单等基本元素。\n",
    "\n",
    "### 系统概述\n",
    "\n",
    "在这个简单的在线购物系统中，有以下几个关键的对象：\n",
    "\n",
    "- **用户（User）**：用户有姓名、地址等属性，可以浏览商品，添加商品到购物车，下订单。\n",
    "- **商品（Product）**：商品有名称、描述、价格等属性。\n",
    "- **购物车（ShoppingCart）**：购物车存储用户想要购买的商品和数量，用户可以添加或删除购物车中的商品。\n",
    "- **订单（Order）**：当用户完成购物并下单时，购物车中的内容会被转换为一个订单，订单包含了所购买的商品、总价等信息。\n",
    "\n",
    "### 类的设计\n",
    "\n",
    "接下来，我们将为每一个关键对象定义一个类，并实现它们的基本功能。\n",
    "\n",
    "#### 用户类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f871dd09-a3de-4c98-ac6c-78a306757e68",
   "metadata": {},
   "outputs": [],
   "source": [
    "class User:\n",
    "    def __init__(self, name, address):\n",
    "        self.name = name\n",
    "        self.address = address\n",
    "        self.shopping_cart = ShoppingCart(self)\n",
    "\n",
    "    def add_product_to_cart(self, product, quantity):\n",
    "        self.shopping_cart.add_product(product, quantity)\n",
    "\n",
    "    def remove_product_from_cart(self, product):\n",
    "        self.shopping_cart.remove_product(product)\n",
    "\n",
    "    def checkout(self):\n",
    "        order = self.shopping_cart.create_order()\n",
    "        if order:\n",
    "            print(f\"订单已创建，订单号: {order.order_id}.\")\n",
    "        else:\n",
    "            print(\"购物车为空，无法下单。\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca19e03a-c97d-4a67-aba0-0a5d2397d692",
   "metadata": {},
   "source": [
    "商品类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "1d37de51-37b8-4014-b908-d1e85b23331c",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Product:\n",
    "    def __init__(self, name, description, price):\n",
    "        self.name = name\n",
    "        self.description = description\n",
    "        self.price = price\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c179d80-cc10-4623-acef-8b942fb44145",
   "metadata": {},
   "source": [
    "购物车类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "2b2deaf5-7b63-48b8-b1c4-4f2194152629",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ShoppingCart:\n",
    "    def __init__(self, user):\n",
    "        self.user = user\n",
    "        self.products = {}  # 商品和对应数量\n",
    "\n",
    "    def add_product(self, product, quantity):\n",
    "        if product in self.products:\n",
    "            self.products[product] += quantity\n",
    "        else:\n",
    "            self.products[product] = quantity\n",
    "\n",
    "    def remove_product(self, product):\n",
    "        if product in self.products:\n",
    "            del self.products[product]\n",
    "\n",
    "    def create_order(self):\n",
    "        if self.products:\n",
    "            return Order(self.user, self.products)\n",
    "        else:\n",
    "            return None\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e10e5991-4059-4bb1-85be-31d13ef89179",
   "metadata": {},
   "source": [
    "订单类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "a12aef8c-41ab-49e5-aa66-9ddf80083f23",
   "metadata": {},
   "outputs": [],
   "source": [
    "import uuid\n",
    "class Order:\n",
    "    def __init__(self, user, products):\n",
    "        self.order_id = str(uuid.uuid4())\n",
    "        self.user = user\n",
    "        self.products = products\n",
    "        self.total_price = sum([product.price * quantity for product, quantity in products.items()])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e583934e-1cfa-4cfe-9933-6b8216db9030",
   "metadata": {},
   "source": [
    "示例使用\n",
    "现在我们来看看如何使用这些类来模拟用户在在线购物系统中的操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "4577336b-6a8e-4920-9684-4b465e15f592",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "订单已创建，订单号: 2e0a8d13-3f13-4fa5-8fdf-ac86ebb1b2bd.\n"
     ]
    }
   ],
   "source": [
    "# 创建一些商品\n",
    "product1 = Product(\"书籍\", \"《Python入门》\", 59.99)\n",
    "product2 = Product(\"电子产品\", \"键盘\", 199.99)\n",
    "\n",
    "# 创建用户\n",
    "user = User(\"张三\", \"北京市朝阳区\")\n",
    "\n",
    "# 用户添加商品到购物车\n",
    "user.add_product_to_cart(product1, 1)\n",
    "user.add_product_to_cart(product2, 1)\n",
    "\n",
    "# 用户下单\n",
    "user.checkout()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0bfeac0-16f4-4f07-b77e-8d0b01b297d4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
